#include "Mainwindow.h"
#include "ui_mainwindow.h"
#include "../common/EdlParser.h"
#include "../common/Entity.h"
#include "Viewer.h"
#include "Plane.h"
#include "Cube.h"
#include "Element.h"
#include "Sphere.h"
#include "Ui_ViewerMainWindow.h"
#include <QFileDialog>
#include <QFile>
#include <QVector>
#include <stdio.h>
#include <QTextStream>
#include <iostream>
#include "GL/glut.h"
#define length(a) ( sizeof ( a ) / sizeof ( *a ) );

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(this->ui->actionOpen,SIGNAL(triggered()),this,SLOT(openFile()));
    connect(this->ui->actionSave,SIGNAL(triggered()),this,SLOT(saveFile()));
    connect(this->ui->actionNew,SIGNAL(triggered()),this,SLOT(newFile()));
    connect(this->ui->lstAllObjects,SIGNAL(itemSelectionChanged()),this,SLOT(selectObject()));
    connect(this->ui->updateButton,SIGNAL(clicked()),this,SLOT(updateType()));
    connect(this->ui->deleteButton,SIGNAL(clicked()),this,SLOT(deleteObject()));
    connect(this->ui->newButton,SIGNAL(clicked()),this,SLOT(newObject()));
    connect(this->ui->line_px,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->line_py,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->line_pz,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->line_vx,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->line_vy,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->line_vz,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->line_scx,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->line_scy,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->line_scz,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->line_r,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->line_g,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->line_b,SIGNAL(editingFinished()),this,SLOT(updateObject()));
    connect(this->ui->checkBox_mv,SIGNAL(clicked()),this,SLOT(updateObject()));
    connect(this->ui->actionCopy,SIGNAL(clicked()),this,SLOT(copyObject()));

    selectedId=-1;
    viewer = new Viewer(this);
    ui->viewerLayout->addWidget(viewer);

    float m[16] = {1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0};
    unsigned char c[3] = {18, 141, 2}; //green
    //unsigned char c[3] = {244, 26, 92}; //pink
    Plane *plane = new Plane(60, c, m);
    viewer->addStaticElement(plane);
    newFile();

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::openFile(QString filename){
    selectedId=-1;
    setWindowTitle(filename);
    parser = new EdlParser();
    parser->parseDocument(filename);

    ui->lstAllObjects->clear();
    objects = parser->getObjects();
    for (int i = 0; i < objects->count();++i) {
        QString name = objects->at(i).getType() + " " + QString::number(objects->at(i).getId());
        ui->lstAllObjects->addItem(name);
    }
    refresh();
}
void MainWindow::openFile() {
    QString filename = QFileDialog::getOpenFileName( this, tr("Open..."), QDir::currentPath(), tr("Environment descriptor files (*.xml *.edf);;All files (*.*)"), 0, QFileDialog::DontUseNativeDialog );
    if (!filename.isNull())
    openFile(filename);
}

void MainWindow::saveFile(QString filename) {

    QDomDocument doc( "Objects" );
    QDomElement root1 = doc.createElement( "world" );
    QDomElement root2 = doc.createElement( "objects" );
    doc.appendChild( root1 );
    root1.appendChild( root2 );
    for (int i = 0; i < objects->count();++i) {
        objects->at(i).getId();
        QDomElement cde = doc.createElement("obstacle");

        cde.setAttribute("position",QString(QString::number(objects->at(i).getPos()[0])+","+QString::number(objects->at(i).getPos()[1])+","+QString::number(objects->at(i).getPos()[2])));
        cde.setAttribute("direction",QString(QString::number(objects->at(i).getDir()[0])+","+QString::number(objects->at(i).getDir()[1])+","+QString::number(objects->at(i).getDir()[2])));
        cde.setAttribute("color",QString(QString::number(objects->at(i).getCol()[0])+","+QString::number(objects->at(i).getCol()[1])+","+QString::number(objects->at(i).getCol()[2])));
        cde.setAttribute("type",objects->at(i).getType());
        cde.setAttribute("id",objects->at(i).getId());
        cde.setAttribute("movable",objects->at(i).getMovable());
        cde.setAttribute("scale",QString(QString::number(objects->at(i).getScale()[0])+","+QString::number(objects->at(i).getScale()[1])+","+QString::number(objects->at(i).getScale()[2])));
        root2.appendChild(cde);
    }

    QFile file( filename );
    if (! file.open( QIODevice::WriteOnly ) )
        exit(1);

    QTextStream ts( &file );
    ts << doc.toString();

    file.close();
}

void MainWindow::saveFile() {
    QString filename = QFileDialog::getSaveFileName(this, tr("Save as..."), QDir::currentPath(), tr("Environment descriptor files (*.xml *.edf);;All files (*.*)"), 0, QFileDialog::DontUseNativeDialog );
    if (!filename.isNull())
    saveFile(filename);
}

void MainWindow::selectObject() {
    int current = ui->lstAllObjects->currentRow();
    ui->lineType->setText(objects->at(current).getType());
    ui->line_px->setValue(objects->at(current).getPos()[0]);
    ui->line_py->setValue(objects->at(current).getPos()[1]);
    ui->line_pz->setValue(objects->at(current).getPos()[2]);
    ui->line_vx->setValue(objects->at(current).getDir()[0]);
    ui->line_vy->setValue(objects->at(current).getDir()[1]);
    ui->line_vz->setValue(objects->at(current).getDir()[2]);
    ui->line_r->setValue(objects->at(current).getCol()[0]);
    ui->line_g->setValue(objects->at(current).getCol()[1]);
    ui->line_b->setValue(objects->at(current).getCol()[2]);
    ui->line_scx->setValue(objects->at(current).getScale()[0]);
    ui->line_scy->setValue(objects->at(current).getScale()[1]);
    ui->line_scz->setValue(objects->at(current).getScale()[2]);
    ui->checkBox_mv->setChecked(objects->at(current).getMovable()==1);
    selectedId=objects->at(current).getId();
    refresh();
}

void MainWindow::updateObject() {
    int current = ui->lstAllObjects->currentRow();
    if (current >= 0){
        float p[3]={ui->line_px->value(),ui->line_py->value(),ui->line_pz->value()};
        (*objects)[current].setPos(p);
        float v[3]={ui->line_vx->value(),ui->line_vy->value(),ui->line_vz->value()};
        (*objects)[current].setDir(v);
        unsigned char c[3]={(unsigned char) ui->line_r->value(),(unsigned char) ui->line_g->value(),(unsigned char) ui->line_b->value()};
        (*objects)[current].setCol(c);
        float sc[3]={ui->line_scx->value(),ui->line_scy->value(),ui->line_scz->value()};
        (*objects)[current].setScale(sc);
        if (ui->checkBox_mv->isChecked())
            (*objects)[current].setMovable(1);
        else
            (*objects)[current].setMovable(0);
        //ui->lstAllObjects->SelectRows=selectedId;
    }
    refresh();
}

void MainWindow::updateType(){
    int current = ui->lstAllObjects->currentRow();
    if (current >= 0){
        (*objects)[current].setType(ui->lineType->text());
        ui->lstAllObjects->clear();
        for (int i = 0; i < objects->count();++i) {
            QString name = objects->at(i).getType() + " " + QString::number(objects->at(i).getId());
            ui->lstAllObjects->addItem(name);
        }
    }
}

void MainWindow::newObject() {
    float p[3]={0,5,0};
    float v[3]={0,0,0};
    unsigned char c[3]={255,255,255};
    float sc[3]={1,1,1};
    if (objects->count()>0){

        Entity temp(objects->at(objects->count()-1).getId()+1,"Box",p,v,c,sc,0);
        objects->append(temp);
        QString name = temp.getType() + " " + QString::number(temp.getId());
        ui->lstAllObjects->addItem(name);
    }
    else{
        Entity temp(1,"Box",p,v,c,sc,0);
        objects->append(temp);
        QString name = temp.getType() + " " + QString::number(temp.getId());
        ui->lstAllObjects->addItem(name);
    }
    refresh();
}

void MainWindow::deleteObject() {
    int current = ui->lstAllObjects->currentRow();

    if (current >= 0 && current < objects->count())
    {
        ui->lstAllObjects->clear();

        objects->remove(current);

        for (int i = 0; i < objects->count();++i) {
            QString name = objects->at(i).getType() + " " + QString::number(objects->at(i).getId());
            ui->lstAllObjects->addItem(name);
            }

    }
    refresh();
}

void MainWindow::newFile(){
    ui->lstAllObjects->clear();
    ui->lineType->clear();
    ui->line_px->clear();
    ui->line_py->clear();
    ui->line_pz->clear();
    ui->line_vx->clear();
    ui->line_vy->clear();
    ui->line_vz->clear();
    ui->line_r->clear();
    ui->line_g->clear();
    ui->line_b->clear();
    ui->line_scx->clear();
    ui->line_scy->clear();
    ui->line_scz->clear();
    ui->checkBox_mv->setChecked(false);
    objects=new QVector<Entity>();
    refresh();
}

void MainWindow::copyObject() {
    int current = ui->lstAllObjects->currentRow();
    if (current >= 0){
        Entity temp(objects->at(objects->count()-1).getId()+1,objects->at(current).getType(),objects->at(current).getPos(),objects->at(current).getDir(),objects->at(current).getCol(),objects->at(current).getScale(),objects->at(current).getMovable());
        objects->append(temp);
        QString name = temp.getType() + " " + QString::number(temp.getId());
        ui->lstAllObjects->addItem(name);
    }
    refresh();
}


void MainWindow::refresh(){
    Cube *cube;
    Sphere *sphere;
    viewer->clear();
    float m[16];
    unsigned char c[3];
    Element *element;

    for (int i = 0; i < objects->count();++i) {
        m = {1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0, objects->at(i).getPos()[0], objects->at(i).getPos()[1], objects->at(i).getPos()[2], 1.0};
                                                                    //objects->at(i).getPos()[0], objects->at(i).getPos()[2]+objects->at(i).getScale()/2, objects->at(i).getPos()[1]

        if (objects->at(i).getId()==selectedId){
            for (int j=0; j<3; j++){
                c[j] = 0;
            }
        }else{
            for (int j=0; j<3; j++){
                c[j] = objects->at(i).getCol()[j];
            }
        }

        if (!objects->at(i).getType().compare(QString("Sphere")))
            element = new Sphere(objects->at(i).getScale(),c,m);
        else
            element = new Cube(objects->at(i).getScale(),c,m);
        viewer->addElement(element);
    }
    //selectedId=-1;
}
